from machine import I2C, ExtInt
from usr.qframe import CurrentApp
from usr.qframe.collections import Int
from usr.qframe.i2c import I2CInterface
from usr.qframe.logging import getLogger
from usr.qframe.threading import Thread


logger = getLogger(__name__)


OUT_TEMP_L = 0x0C
OUT_TEMP_H = 0x0D
WHO_AM_I = 0x0F  # default: 0x11
USER_CAL = 0x13  # 0x13 ~ 0x1A
NVM_WR = 0x1E
TEMP_CFG = 0x1F
CTRL_REG1 = 0x20  # default: 0x07
CTRL_REG2 = 0x21
CTRL_REG3 = 0x22
CTRL_REG4 = 0x23
CTRL_REG5 = 0x24
CTRL_REG6 = 0x25
REFERENCE = 0x26
STATUS_REG = 0x27
OUT_X_L = 0x28
OUT_X_H = 0x29
OUT_Y_L = 0x2A
OUT_Y_H = 0x2B
OUT_Z_L = 0x2C
OUT_Z_H = 0x2D
FIFO_CTRL_REG = 0x2E
FIFO_SRC_REG = 0x2F
INT1_CFG = 0x30
INT1_SOURCE = 0x31
INT1_THS = 0x32
INT1_DURATION = 0x33
INT2_CFG = 0x34
INT2_SOURCE = 0x35
INT2_THS = 0x36
INT2_DURATION = 0x37
CLICK_CFG = 0x38
CLICK_SRC = 0x39
CLICK_THS = 0x3A
TIME_LIMIT = 0x3B
TIME_LATENCY = 0x3C
TIME_WINDOW = 0x3D
ACT_THS = 0x3E
ACT_DURATION = 0x3F


class Sc7a20Driver(I2CInterface):

    def readreg(self, addr, size=1, delay=20):
        data = self.read(bytes([addr]), size=size, delay=delay)
        if size == 1:
            return data[0]
        return data

    def writereg(self, addr, value):
        return self.write(bytes([addr]), bytes([value]))

    def get_chip_id(self):
        return self.readreg(WHO_AM_I)

    def init(self):
        if self.get_chip_id() != 0x11:
            raise ValueError('chip id error')
        self.writereg(CTRL_REG1, 0x2F)
        self.writereg(CTRL_REG2, 0x04)
        self.writereg(CTRL_REG4, 0x98)
        self.writereg(NVM_WR, 0x05)
        self.writereg(0x57, 0x08)
        self.writereg(0x25, 0x02)
        self.writereg(0x3a, 0x0A)  # click阈值
        self.writereg(0x3b, 0x05)
        self.writereg(0x3c, 0x01)
        self.writereg(0x38, 0x64)  # 间隔10s
        self.writereg(0x22, 0x80)

    def read_raw_data(self):
        data = self.readreg(OUT_X_L, 6)
        return (Int.from_bytes(data[i:i+2], 'little', signed=True) for i in range(0, 6, 2))


class GSensorService(object):

    def __init__(self, app=None):
        self.i2c2 = I2C(I2C.I2C2, I2C.STANDARD_MODE)
        self.driver = Sc7a20Driver(self.i2c2, 0x18)
        self.ext1 = ExtInt(ExtInt.GPIO29, ExtInt.IRQ_FALLING, ExtInt.PULL_PU, self.sensor_clicked_handler)
        if app:
            self.init_app(app)

    def init_app(self, app):
        app.register('gsensor', self)

    def load(self):
        logger.info('load {}'.format(type(self).__name__))
        self.ext1.enable()
        self.driver.init()

    def sensor_clicked_handler(self, *args, **kwargs):
        logger.debug('{} sensor_clicked_handler'.format(type(self).__name__))
        try:
            Thread(target=CurrentApp().job_service.report_co_event).start()
        except Exception as e:
            logger.debug('sensor_clicked_handler get error: {}'.format(e))
